﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.Diagnostics;

namespace nudota
{
    public partial class update : Form
    {
        long m_last_bytes;
        Speeder m_speed=new Speeder();
        WebClient m_client = new WebClient();
        PerformanceRender m_pr = new PerformanceRender();
        Random m_r = new Random();
        string m_url, m_filename;
        bool downloaded = false;

        public update()
        {
            //m_speed.put(1024*1024);
            //Thread.Sleep(10*1000);
            //m_speed.put(0);
            //double t = m_speed.get();

            //m_pr.put(0);
            //m_pr.put(10);
            //m_pr.put(20);
            //m_pr.put(30);
            //m_pr.put(40);
            //m_pr.put(50);

            InitializeComponent();
        }

        private string get_temp_filename()
        {
            IDictionary	env = Environment.GetEnvironmentVariables();
            foreach (DictionaryEntry de in env)
            {
                string key=(string)de.Key;
                if (key.ToUpper()=="TEMP")
                    return (string)de.Value+"\\nudota.msi";
            }

            if (saveFileDialog1.ShowDialog() == DialogResult.OK)
                return saveFileDialog1.FileName;
            return null;
        }

        public void go(String url)
        {
            if (m_filename != null)
            {
                m_last_bytes = 0;
                m_client.DownloadFileAsync(new Uri(url), m_filename);
                timer1.Enabled = true;
                button_cancel.Enabled = true;
                button_go.Enabled = false;
                label_file.Enabled = false;
                progressBar1.Value = 0;
                label_url.Text = url;
                label_file.Text = m_filename;
            }
        }

        private void onProgressChanged(Object sender, DownloadProgressChangedEventArgs e)
        {
            progressBar1.Value = e.ProgressPercentage;
            m_speed.put((int)(e.BytesReceived - m_last_bytes));
            m_last_bytes = e.BytesReceived;
        }

        private void onDownloadCompleted(Object sender,	AsyncCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                button_go.Enabled = true;
                if (!e.Cancelled) MessageBox.Show(e.Error.Message);
            }
            else
            {
                label_file.Enabled = true;
                downloaded = true;
                label_file.LinkColor = Color.Fuchsia;
            }

            progressBar1.Value = 0;
            //timer1.Enabled = false;
            button_cancel.Enabled = false;
            label_file.Enabled = true;
            label_speed.Text = "KB/S";
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            m_speed.put(0);
            m_pr.put((int)m_speed.get());
            //m_pr.draw(this.label_graph);
            m_pr.draw(this.pictureBox1);
            label_speed.Text = (m_speed.get()/1024).ToString("N") + "KB/S";
        }

        private void button_go_Click(object sender, EventArgs e)
        {
            go(m_url);
        }

        private void button_cancel_Click(object sender, EventArgs e)
        {
            m_client.CancelAsync();
            //onDownloadCompleted(null, new AsyncCompletedEventArgs(null, true, null));
        }

        private void update_Load(object sender, EventArgs e)
        {
            //label_graph.Paint += new PaintEventHandler(this.timer1_Tick);
            m_client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(this.onProgressChanged);
            m_client.DownloadFileCompleted += new AsyncCompletedEventHandler(this.onDownloadCompleted);
            label_file.Text = m_filename = get_temp_filename();
            label_url.Text = m_url = "http://192.168.0.111/1.wmv";
        }

        private void update_FormClosed(object sender, FormClosedEventArgs e)
        {
            m_client.CancelAsync();
        }

        private void label_graph_Paint(object sender, PaintEventArgs e)
        {
            m_pr.draw(e.Graphics, pictureBox1.Width, pictureBox1.Height);
            //m_pr.draw((PictureBox)sender);
        }

        private void label_url_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                LinkLabel ll = (LinkLabel)sender;
                Process.Start(ll.Text);
            }
        }

        private void label_url_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button==MouseButtons.Right)
            {
                contextMenuStrip1.Tag = sender;
                contextMenuStrip1.Show((Control)sender, e.X, e.Y);
            }
        }

        private void label_file_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            if (downloaded || e.Button != MouseButtons.Left)
            {
                label_url_LinkClicked(sender, e);
            }
            else if (saveFileDialog1.ShowDialog() == DialogResult.OK)
            {
                LinkLabel ll = (LinkLabel)sender;
                m_filename = saveFileDialog1.FileName;
                ll.Text = m_filename;
            }
        }

        private void 打开OToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                LinkLabel ll=(LinkLabel)ActiveControl;
                Process.Start(ll.Text);
            }
            catch(Exception){}
        }

        private void 复制URIToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                LinkLabel ll = (LinkLabel)ActiveControl;
                Clipboard.SetText(ll.Text);
            }
            catch (Exception) { }
        }

        private void contextMenuStrip1_Opening(object sender, CancelEventArgs e)
        {
            if (ActiveControl==label_file)
                打开OToolStripMenuItem.Enabled = downloaded;
        }
    }

    sealed class Speeder
    {
        public void put(int n)
        {
            long now = System.DateTime.Now.Ticks;
            long threshhold = now - m_duration;
            while (m_times.Count > 0 && m_times.Peek() < threshhold)
            {
                m_times.Dequeue();
                m_total -= m_numbers.Dequeue();
            }

            m_total += n;
            m_numbers.Enqueue(n);
            m_times.Enqueue(now);
            if (m_times.Count < 2) m_value = 0;
            else m_value = (double)m_total / (now - m_times.Peek()) * (1000 * 1000 * 10);
        }

        public double get()
        {
            return m_value;
        }

        private int m_total = 0;
        private double m_value = 0;
        private long m_duration = 10 * 1000 * 1000 * 10;   //10 seconds
        private Queue<int> m_numbers = new Queue<int>();
        private Queue<long> m_times = new Queue<long>();
    }
}